using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Threading;
namespace DBRandomGenerator
{
    /// <summary>
    ///  Modified November 9th
    ///             ---- moved most of the column related processing into the Row Object 
    ///             ---- cleaned out as much of it from the Table itself as possible so as to allow for better processing
    /// </summary>
    public class RDGenTable
    {
        #region "Private Variables"
        private string _Name;
        List<Column> _TableColumns = new List<Column>();
        private InsertStatement _InsertStatement = new InsertStatement();
        StreamWriter sr;

        #endregion
        
        #region "Properties"
        public List<Column> TableColumns 
        {
            get { return _TableColumns; }
            set { _TableColumns = value; }
        }

        public string Name 
        {
            get { return _Name; }
            set { _Name = value; }
        }

        public RDGenTable(string TableName)
        {
            this.Name = TableName;
            this.TableColumns = DCM.GetColumnList(this.Name);
            _InsertStatement.TableName = this.Name;
            PopulateColumnNames();
 
        }

        // holds the rows created and associated with this table
        public Row[] rows { get; set; }

        public void GenerateInsertStatements(int iRequiredRows)
        {
            rows  = new Row[iRequiredRows];
            using (ThreadPoolWait tpw = new ThreadPoolWait())
            {
                for (int i = 0; i < iRequiredRows; i++)
                {
                    Row row = new Row(this.Name, this.TableColumns);
                    this.rows[i] = row;
                    tpw.QueueUserWorkItem(new WaitCallback(ThreadPoolCallback), this.rows[i]);
                }
                 tpw.WaitOne(); // wait indefinitely
            }
            WriteStatementToFile();
        }

        Object locker = new object();
        // Wrapper method for use with thread pool.
        public void ThreadPoolCallback(Object threadContext)
        {
            try
            {
                lock (locker)
                {
                Row row = (Row) threadContext;
                row.GenerateInsertStatement();
                 }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.GetBaseException().Message + "  :  This is in the stream writing area");
            }
 
        }

        private void WriteStatementToFile( )
        {
            try
            {
                lock (locker)
                {
                    using (sr = new StreamWriter(this.Name + ".sql"))
                    {
                        //print the row insert
                        for (int a = 0; a < rows.Length; a++)
                        {
                            sr.WriteLine(rows[a].GeneratedInsertStatement);
                            sr.WriteLine("");
                            Debug.WriteLine("Just wrote line " + (a).ToString() + " at " + DateTime.Now.ToString("HH:mm:ss"));
                        }
                        sr.Close();
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.GetBaseException().Message + "  :  This is in the stream writing area");
            }
 
        }


        private void WriteStatementToFile(int i, String insertStatement)
        {
            lock (sr)
            {
                using (sr = new StreamWriter(this.Name + ".sql"))
                {
                    sr.WriteLine(insertStatement);
                    sr.WriteLine("");
                    Debug.WriteLine("Just wrote line " + (i).ToString() + " at " + DateTime.Now.ToString("HH:mm:ss"));
                    sr.Close();
                }
            }
        }


        public string GetInsertStatement()
        {
            try
            {
                lock (_Name)
                {
                   // PopulateData();
                    string InsertStatement = _InsertStatement.ToString();
                    _InsertStatement.ColumnValues = String.Empty;
                    return InsertStatement;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        private void PopulateColumnNames()
        {
            foreach (Column TableColumn in TableColumns)
            {
                if (TableColumn.IncludeColumn)
                {
                    _InsertStatement.ColumnNames = _InsertStatement.ColumnNames + TableColumn.Name;

                    _InsertStatement.ColumnNames += ",";
                }
            }
            if (_InsertStatement.ColumnNames.EndsWith(","))
            {
                _InsertStatement.ColumnNames = _InsertStatement.ColumnNames.Remove(_InsertStatement.ColumnNames.Length - 1, 1);
            }
        }

        public string GetRandomValue(Column TableColumn)
        {
            string ColumnValue = String.Empty;
            switch (TableColumn.DataType.ToLower())
            {
                case "uniqueidentifier":
                    ColumnValue = "'" + DataBuilder.GetUniqueIdentifier(TableColumn) + "'";
                    break;
                case "sqlvariant":
                    ColumnValue = "'" + DataBuilder.GetSqlVariant(TableColumn) + "'";
                    break;
                case "bit":
                    ColumnValue = DataBuilder.GetBit();
                    break;
                case "int":
                    if (TableColumn.Name.Contains("id"))
                        ColumnValue = DataBuilder.GetID(TableColumn);
                    else
                        ColumnValue = DataBuilder.GetInt(TableColumn);
                    break;
                case "bigint":
                case "decimal":
                case "float":
                case "money":
                case "numeric":
                case "real":
                case "smallmoney":

                    ColumnValue = DataBuilder.GetBigInt(TableColumn);
                    break;
                case "datetime":
                case "smalldatetime":
                    ColumnValue = "'" + DataBuilder.GetDateTime() + "'";
                    break;

                case "nchar":
                case "char":
                    ColumnValue = "'" + DataBuilder.GetChar(TableColumn) + "'";
                    break;
                case "varchar":
                case "nvarchar":
                    ColumnValue = "'" + DataBuilder.GetText(TableColumn) + "'";
                    break;

                case "binary":
                case "varbinary":
                    ColumnValue = "'" + DataBuilder.GetBinary(TableColumn) + "'";
                    break;
                case "tinyint":
                    ColumnValue = DataBuilder.GetTinyInt();
                    break;
                case "smallint":
                    ColumnValue = DataBuilder.GetSmallInt(TableColumn);
                    break;
                case "text":
                case "ntext":
                    ColumnValue = "'" + DataBuilder.GetText(TableColumn) + "'";
                    break;

            }
            return ColumnValue;
        }
        
        #endregion
    }
}
